package cn.aran.basic.service.impl;

import cn.aran.basic.constants.BaseConstants;
import cn.aran.basic.exception.BusinessException;
import cn.aran.basic.service.IVerifyCodeService;
import cn.aran.basic.utils.MailUtils;
import cn.aran.basic.utils.StrUtils;
import cn.aran.basic.utils.VerifyCodeUtils;
import cn.aran.basic.vo.RegisterVo;
import cn.aran.user.domain.User;
import cn.aran.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String graph(String imageCodeKey) {
        if (StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("必要参数为空!");
        }
        String code = StrUtils.getComplexRandomString(4);
        redisTemplate.opsForValue().set(imageCodeKey, code, 5, TimeUnit.MINUTES);
        String base64Str = VerifyCodeUtils.VerifyCode(100, 35, code);
        return base64Str;
    }

    /**
    * @Title: smsCode
    * @Description: 发送短信验证码
    * @Author: Aran
    * @Version: 1.0
    * @Date:  2022/7/9 17:39
    * @Parameters: [phoneRegisterVo]
    * @Return void
    */
    @Override
    public void smsCode(RegisterVo registerVo) {
        String phone = registerVo.getPhone();
        String type = registerVo.getType();
        String email = registerVo.getEmail();
        // 判断参数是为空
        if (StringUtils.isEmpty(email) && StringUtils.isEmpty(phone)){
            throw new BusinessException("请输入正确参数!");
        }
        if (StringUtils.isEmpty(type)){
            throw new BusinessException("请输入正确参数!");
        }
        // 判断验证码业务
        if ("phoneRegister".equals(type)){ // 手机注册
            // 校验图形码
            checkImageCode(registerVo);
            // 判断手机号是否已被注册
            User user = userMapper.loadByPhone(phone);
            if (user != null){
                throw new BusinessException("用户已注册,请登录!");
            }
            sendCode(BaseConstants.VerifyCodeConstant.PHONE_REGISTER_PREFIX,phone);
        }else if ("binder".equals(type)){
            sendCode(BaseConstants.VerifyCodeConstant.WECHAT_BINDER_PREFIX,phone);
        }else if ("login".equals(type)){
            sendCode(BaseConstants.VerifyCodeConstant.PHONE_LOGIN_PREFIX,phone);
        }else if ("emailRegister".equals(type)){ // 邮箱注册
            checkImageCode(registerVo);
            // 判断邮箱是否已被注册
            User user = userMapper.loadByEmail(email);
            if (user != null){
                throw new BusinessException("用户已注册,请登录!");
            }
            sendEmailCode(BaseConstants.VerifyCodeConstant.EMAIL_REGISTER_PREFIX,email);
        }

    }

    /**
    * @Title: checkImageCode
    * @Description: 校验图形码
    * @Author: Aran
    * @Version: 1.0
    * @Date:  2022/7/10 19:58
    * @Parameters: [registerVo]
    * @Return void
    */
    public void checkImageCode(RegisterVo registerVo){
        String imageCodeValue = registerVo.getImageCodeValue();
        String imageCodeKey = registerVo.getImageCodeKey();
        if (StringUtils.isEmpty(imageCodeValue)
            || StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请输入正确参数!");
        }

        // 判断图形验证码在Redis中存在且正确
        Object imageCodeRedis = redisTemplate.opsForValue().get(imageCodeKey);
        // 图形验证码不存在
        if (imageCodeRedis == null){
            throw new BusinessException("请输入验证码!");
        }
        // 图形验证码存在,判断是否正确
        if (!imageCodeRedis.toString().equalsIgnoreCase(imageCodeValue)){
            throw new BusinessException("验证码错误!请重新输入!");
        }
    }

    /**
    * @Title: sendCode
    * @Description: 发送验证码
    * @Author: Aran
    * @Version: 1.0
    * @Date:  2022/7/10 20:01
    * @Parameters: [businessKey, phone]
    * @Return void
    */
    public void sendCode(String businessKey, String phone){
        // 保存号码在redis
        String smsCodeKey = businessKey + phone;
        Object smsCodeRedis = redisTemplate.opsForValue().get(smsCodeKey);
        // 判断短信验证码是否为空
        String registerSmsCode = "";
        if (smsCodeRedis == null){
            registerSmsCode = StrUtils.getComplexRandomString(4);
        }else {
            // 判断是否过期
            String[] smsCodeRedises = smsCodeRedis.toString().split(":");
            Long oldTime = Long.valueOf(smsCodeRedises[0]);
            Long newTime = System.currentTimeMillis();
            if (newTime - oldTime <= 60*1000){
                throw new BusinessException("请一分钟后重试!");
            }
            registerSmsCode = smsCodeRedises[1];
        }
        // 将短信验证码存放在Redis中
        String smsCodeValue = registerSmsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(smsCodeKey, smsCodeValue, 3, TimeUnit.MINUTES);
        // 发送短信验证码
        // SendSmsCodeUtil.sendRegisterSmsCode(phone,"用户您的注册验证码为:" + registerSmsCode);
        System.out.println(registerSmsCode);
    }

    /**
    * @Title: sendEmailCode
    * @Description: 发送邮箱验证码
    * @Author: Aran
    * @Version: 1.0
    * @Date:  2022/7/12 11:23
    * @Parameters: [businessKey, email]
    * @Return void
    */
    public void sendEmailCode(String businessKey, String email){
        // 保存邮箱在redis
        String emailCodeKey = businessKey + email;
        Object emailCodeRedis = redisTemplate.opsForValue().get(emailCodeKey);
        // 判断邮箱验证码是否为空
        String registerEmailCode = "";
        if (emailCodeRedis == null){
            registerEmailCode = StrUtils.getComplexRandomString(4);
        }else {
            // 判断是否过期
            String[] emailCodeRedises = emailCodeRedis.toString().split(":");
            Long oldTime = Long.valueOf(emailCodeRedises[0]);
            Long newTime = System.currentTimeMillis();
            if (newTime - oldTime <= 60*1000){
                throw new BusinessException("请一分钟后重试!");
            }
            registerEmailCode = emailCodeRedises[1];
        }
        // 将邮箱验证码存放在Redis中
        String smsCodeValue = registerEmailCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(emailCodeKey, smsCodeValue, 3, TimeUnit.MINUTES);
        // 发送邮箱验证码
        MailUtils.sendMail(email,"你的验证码为:"+ registerEmailCode ,"宠物乐园验证码");
    }
}
